


#include "vm.h"
#include "header.h"
#include "state.h"

#include <kernel/block/block.h>

vm *vm_request (const char *_name)
{
	vm *v;

	v = block_request (sizeof (vm));

	v->ID = userid_request ();
	v->WaitQueue = handle_request (_name, v->ID);
	v->AgentTable = NULL;
	v->AgentTableSize = 0;

	return v;
}


void vm_release (vm *_vm)
{
	int i;

	for (i = 0; i < _vm->AgentTableSize; ++i)
	{
		vm_agent_release (_vm->AgentTable [i]);
	}

	block_release (_vm->AgentTable);
	handle_release (_vm->WaitQueue);
	userid_release (_vm->ID);
	block_releas (_vm);
}


int vm_load (vm *_vm, handle _bytestream)
{
	vm_Header head;
	handle input;
	int i;

	handle_peak (_bytestream, (char *) &head, sizeof (vm_Header));

	input = handle_request (head.AgentName, _vm->ID);

	if (input == BADHANDLE)
	{
		return -1;
	}

	++_vm->AgentTableSize;
	_vm->AgentTable = (vm_Agent **) block_resize (_vm->AgentTable, sizeof (vm_Agent) * _vm->AgentTableSize);
	_vm->AgentTable [_vm->AgentTableSize - 1] = vm_agent_request (_bytestream, _vm->ID);

	return vm_agent_wake (_vm->AgentTable [_vm->AgentTableSize - 1]);
}


int vm_run (vm *_vm)
{
	vm_State state;

	while (vm_state_pop (&state, _vm->WaitQueue) == 0)
	{
		if (vm_state_resume (&state, 10) == 0)
		{
			vm_state_push (&state, _vm->WaitQueue);
		}
	}

	return 0;
}


int vm_spawn (vm *_vm, const char *_agent)
{
	int i;
	vm_State *state;

	for (i = 0; i < _vm->AgentTableSize; ++i)
	{
		if (stringequal (_vm->AgentTable [i]->Header.AgentName, _agent))
		{
			return vm_state_push (vm_state_request (_vm->AgentTable [i]), _vm->WaitQueue);
		}
	}

	return -1;
}


